#pragma once
#include<iostream>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<cstdlib>
#include<cstring>
#include<pthread.h>

#define LONG 5
using namespace std;
class TcpServer{
    private:
        int port; 
        int listen_sock;
        static pthread_mutex_t lock;
        static TcpServer* ptr;
        TcpServer(int _port):port(_port),listen_sock(-1)
        {}
    public:
        static TcpServer* getTcpobj(int post)
        {
            if(ptr==nullptr){
                pthread_mutex_lock(&lock);
                if(ptr==nullptr){
                    ptr=new TcpServer(post);
                    ptr->init();
                    return ptr;
                }
                pthread_mutex_unlock(&lock);
            }
            return ptr;
        }
        void init()
        {
            Sock();
            Bind();
            Listen();
        }
        void Sock()
        {
            listen_sock=socket(AF_INET,SOCK_STREAM,0);
            if(listen_sock<0){
                cerr<<"socket error..."<<endl;
                exit(1);
            }
            int opt=1;
            setsockopt(listen_sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
            cout<<"socket success..."<<endl;
        }
        void Bind()
        {
            struct sockaddr_in own;
            memset(&own,0,sizeof(own));
            own.sin_family=AF_INET;
            own.sin_port=htons(port);
            own.sin_addr.s_addr=INADDR_ANY;
            if(bind(listen_sock,(struct sockaddr*)&own,sizeof(own))<0){
                cerr<<"bind error..."<<endl;
                exit(2);
            }
            cout<<"bind success..."<<endl;
        }
        void Listen()
        {
            if(listen(listen_sock,LONG)<0){
                cerr<<"listen error..."<<endl;
                exit(3);
            }
            cout<<"listen success..."<<endl;
        }
        int isSock(){
            return listen_sock;
        }
    ~TcpServer(){}
};
TcpServer* TcpServer::ptr=nullptr;
pthread_mutex_t TcpServer::lock=PTHREAD_MUTEX_INITIALIZER;